package utils.sl651;

/**
 * SL651-2014水文监测数据通信规约解析器（十六进制编码专用）
 * 
 * 专门用于解析十六进制编码的SL651报文
 */
public class SL651HexDecoder {
    
    /**
     * 解析SL651十六进制编码上行报文
     * 
     * @param hexMessage 十六进制编码的报文字符串
     * @return 解析后的消息对象
     */
    public static SL651Message decode(String hexMessage) {
        // 使用十六进制编码专用解析器进行基础解析
        SL651Message message = SL651HexMessageParser.parseUplinkMessage(hexMessage);
        if (message.isValid()) {
            // 根据功能码进行深度解析
            enhanceMessageWithFunctionCode(message);
            // 添加解析摘要信息
            addSummaryInfo(message);
        }
        
        return message;
    }
    
    /**
     * 批量解析多个十六进制编码报文
     * 
     * @param hexMessages 十六进制编码报文数组
     * @return 解析结果数组
     */
    public static SL651Message[] decodeBatch(String[] hexMessages) {
        SL651Message[] results = new SL651Message[hexMessages.length];
        for (int i = 0; i < hexMessages.length; i++) {
            results[i] = decode(hexMessages[i]);
        }
        return results;
    }
    
    /**
     * 根据功能码进行深度解析
     */
    private static void enhanceMessageWithFunctionCode(SL651Message message) {
        String functionCode = message.getFunctionCode();
        switch (functionCode) {
            case SL651Protocol.FUNC_LINK_MAINTAIN:
                SL651FunctionCodeParser.parseLinkMaintainReport(message);
                break;
                
            case SL651Protocol.FUNC_TEST_REPORT:
                SL651FunctionCodeParser.parseTestReport(message);
                break;
                
            case SL651Protocol.FUNC_EVEN_TIME_REPORT:
                SL651FunctionCodeParser.parseConfigReport(message);
                break;
                
            case SL651Protocol.FUNC_TIMER_REPORT:
                SL651FunctionCodeParser.parseTimerReport(message);
                break;
                
            case SL651Protocol.FUNC_ADD_REPORT:
                SL651FunctionCodeParser.parseAddReport(message);
                break;
                
            case SL651Protocol.FUNC_HOUR_REPORT:
                SL651FunctionCodeParser.parseHourReport(message);
                break;
                
            case SL651Protocol.FUNC_ARTIFICIAL_REPORT:
                SL651FunctionCodeParser.parseManualDataReport(message);
                break;
                
            case SL651Protocol.FUNC_PICTURE_REPORT:
                SL651FunctionCodeParser.parsePictureReport(message);
                break;
                
            case SL651Protocol.FUNC_QUERY_REALTIME:
                SL651FunctionCodeParser.parseRealTimeReport(message);
                break;
                
            case SL651Protocol.FUNC_WATER_PUMP:
                SL651FunctionCodeParser.parseWaterPumpReport(message);
                break;
                
            case SL651Protocol.FUNC_GATE:
                SL651FunctionCodeParser.parseGateReport(message);
                break;
                
            default:
                message.addDataElement("MESSAGE_TYPE", "未知类型报文");
                message.addDataElement("DESCRIPTION", "功能码 " + functionCode + " 暂不支持");
                break;
        }
    }
    
    /**
     * 添加解析摘要信息
     */
    private static void addSummaryInfo(SL651Message message) {
        StringBuilder summary = new StringBuilder();
        
        // 基本信息摘要
        summary.append("站点: ").append(message.getStationAddress());
        summary.append(", 类型: ").append(SL651CommonUtil.getFunctionCodeDescription(message.getFunctionCode()));
        summary.append(", 时间: ").append(SL651CommonUtil.parseBcdTime(message.getReportTime()));

        // 状态摘要
        if (message.isCrcValid()) {
            summary.append(" [校验通过]");
        } else {
            summary.append(" [校验失败]");
        }
        
        message.addDataElement("SUMMARY", summary.toString());
        
        // 数据质量评估
        assessDataQuality(message);
    }
    
    /**
     * 评估数据质量
     */
    private static void assessDataQuality(SL651Message message) {
        int qualityScore = 100;
        StringBuilder qualityNotes = new StringBuilder();
        
        // CRC校验
        if (!message.isCrcValid()) {
            qualityScore -= 50;
            qualityNotes.append("CRC校验失败; ");
        }
        
        // 数据完整性检查
        int dataElementCount = message.getDataElements().size();
        if (dataElementCount < 3) {
            qualityScore -= 20;
            qualityNotes.append("数据元素较少; ");
        }
        
        // 时间合理性检查
        if (message.getObserveDateTime() == null) {
            qualityScore -= 10;
            qualityNotes.append("观测时间格式异常; ");
        } else {
            // 检查时间是否在合理范围内
            java.time.LocalDateTime now = java.time.LocalDateTime.now();
            java.time.LocalDateTime observeTime = message.getObserveDateTime();
            
            if (observeTime.isAfter(now.plusMinutes(5))) {
                qualityScore -= 15;
                qualityNotes.append("观测时间超前; ");
            } else if (observeTime.isBefore(now.minusDays(1))) {
                qualityScore -= 10;
                qualityNotes.append("观测时间过旧; ");
            }
        }
        
        // 数值合理性检查（简单验证）
        String rainfall = message.getDataElement(SL651Protocol.ELEM_CURRENT_RAINFALL);
        if (rainfall != null) {
            try {
                double value = Double.parseDouble(rainfall);
                if (value < 0 || value > 1000) { // 不合理的降水量
                    qualityScore -= 15;
                    qualityNotes.append("降水量数值异常; ");
                }
            } catch (NumberFormatException e) {
                qualityScore -= 10;
                qualityNotes.append("降水量格式错误; ");
            }
        }
        
        String waterLevel = message.getDataElement(SL651Protocol.ELEM_WATER_LEVEL);
        if (waterLevel != null) {
            try {
                double value = Double.parseDouble(waterLevel);
                if (value < -10 || value > 50) { // 不合理的水位
                    qualityScore -= 15;
                    qualityNotes.append("水位数值异常; ");
                }
            } catch (NumberFormatException e) {
                qualityScore -= 10;
                qualityNotes.append("水位格式错误; ");
            }
        }
        
        String voltage = message.getDataElement(SL651Protocol.ELEM_VOLTAGE);
        if (voltage != null) {
            try {
                double value = Double.parseDouble(voltage);
                if (value < 8.0 || value > 20.0) { // 不合理的电压
                    qualityScore -= 10;
                    qualityNotes.append("电压超出正常范围; ");
                }
            } catch (NumberFormatException e) {
                qualityScore -= 5;
                qualityNotes.append("电压格式错误; ");
            }
        }
        
        // 水质参数检查
        String pH = message.getDataElement(SL651Protocol.ELEM_PH);
        if (pH != null) {
            try {
                double value = Double.parseDouble(pH);
                if (value < 0 || value > 14) { // pH值超出范围
                    qualityScore -= 8;
                    qualityNotes.append("pH值超出正常范围; ");
                }
            } catch (NumberFormatException e) {
                qualityScore -= 5;
                qualityNotes.append("pH值格式错误; ");
            }
        }
        
        // 温度检查
        String waterTemp = message.getDataElement(SL651Protocol.ELEM_WATER_TEMP);
        if (waterTemp != null) {
            try {
                double value = Double.parseDouble(waterTemp);
                if (value < -5 || value > 50) { // 不合理的水温
                    qualityScore -= 8;
                    qualityNotes.append("水温超出正常范围; ");
                }
            } catch (NumberFormatException e) {
                qualityScore -= 5;
                qualityNotes.append("水温格式错误; ");
            }
        }
        
        // 时间序列数据质量检查
        String functionCode = message.getFunctionCode();
        if (SL651Protocol.FUNC_HOUR_REPORT.equals(functionCode)) {
            String validRate = message.getDataElement("DRP_VALID_RATE");
            if (validRate != null) {
                try {
                    double rate = Double.parseDouble(validRate.replace("%", ""));
                    if (rate < 50) { // 有效数据率过低
                        qualityScore -= 10;
                        qualityNotes.append("时间序列数据有效率过低; ");
                    }
                } catch (NumberFormatException ignored) {}
            }
        }
        
        // 设备状态检查
        String deviceHealth = message.getDataElement("DEVICE_HEALTH");
        if ("故障".equals(deviceHealth)) {
            qualityScore -= 20;
            qualityNotes.append("设备故障报警; ");
        }
        
        // 质量等级判定
        String qualityLevel;
        if (qualityScore >= 90) qualityLevel = "优秀";
        else if (qualityScore >= 80) qualityLevel = "良好";
        else if (qualityScore >= 70) qualityLevel = "一般";
        else if (qualityScore >= 60) qualityLevel = "较差";
        else qualityLevel = "很差";
        
        message.addDataElement("DATA_QUALITY_SCORE", String.valueOf(qualityScore));
        message.addDataElement("DATA_QUALITY_LEVEL", qualityLevel);
        
        if (qualityNotes.length() > 0) {
            message.addDataElement("DATA_QUALITY_NOTES", qualityNotes.toString());
        }
        
        // 添加详细的质量报告
        generateQualityReport(message, qualityScore);
    }
    
    /**
     * 生成质量报告
     */
    private static void generateQualityReport(SL651Message message, int qualityScore) {
        StringBuilder report = new StringBuilder();
        
        if (qualityScore >= 90) {
            report.append("数据质量优秀，可以直接使用");
        } else if (qualityScore >= 80) {
            report.append("数据质量良好，建议检查小问题");
        } else if (qualityScore >= 70) {
            report.append("数据质量一般，需要进一步验证");
        } else if (qualityScore >= 60) {
            report.append("数据质量较差，谨慎使用");
        } else {
            report.append("数据质量很差，不建议使用");
        }
        
        message.addDataElement("QUALITY_REPORT", report.toString());
    }
    
    /**
     * 获取BCD编码值
     * BCD编码中每个十六进制字符代表一个十进制数字
     * 例如："59" 表示数字 59 (十进制)
     */
    private static String getBcdValue(String bcdHex) {
        // BCD编码中，每个十六进制字符代表一个十进制数字
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < bcdHex.length(); i++) {
            char c = bcdHex.charAt(i);
            // 确保字符是有效的十六进制字符
            if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
                // 对于BCD编码，十六进制字符直接对应十进制数字
                if (c >= 'A' && c <= 'F') {
                    // A-F 对应 10-15
                    result.append((char)(c - 'A' + 10));
                } else {
                    // 0-9 直接使用
                    result.append(c);
                }
            } else {
                // 非法字符，直接返回原始值
                return bcdHex;
            }
        }
        return result.toString();
    }
}